package simpledb.index;

import simpledb.storage.PageId;

import java.util.Objects;

/**
 * BTreePageId 是 B+ 树中各种页面（内部节点、叶子节点、根指针页、头页）的唯一标识符。
 *
 * 每个页面 ID 包含三个信息：
 * - 表 ID (tableId)
 * - 页面号 (pgNo)
 * - 页面类型 (pgcateg)
 */
public class BTreePageId implements PageId {

    // 页面类型常量定义
    public final static int ROOT_PTR = 0; // 根指针页
    public final static int INTERNAL = 1; // 内部节点页
    public final static int LEAF     = 2; // 叶子节点页
    public final static int HEADER   = 3; // 头部信息页（如空闲页管理）

    /**
     * 将页面类型编码转换为字符串表示。
     *
     * @param categ 页面类型编码
     * @return 字符串形式的页面类型
     */
    static public String categToString(int categ) {
        switch (categ) {
            case ROOT_PTR:
                return "ROOT_PTR";
            case INTERNAL:
                return "INTERNAL";
            case LEAF:
                return "LEAF";
            case HEADER:
                return "HEADER";
            default:
                throw new IllegalArgumentException("无效的页面类型");
        }
    }

    private final int tableId; // 所属表的ID
    private final int pgNo;   // 页面编号
    private final int pgcateg; // 页面类型

    /**
     * 构造函数：创建一个指定表、页面编号和类型的页面ID对象。
     *
     * @param tableId 表ID
     * @param pgNo 页面编号
     * @param pgcateg 页面类型（ROOT_PTR, INTERNAL, LEAF, HEADER）
     */
    public BTreePageId(int tableId, int pgNo, int pgcateg) {
        this.tableId = tableId;
        this.pgNo = pgNo;
        this.pgcateg = pgcateg;
    }

    /**
     * 获取该页面所属的表ID。
     */
    public int getTableId() {
        return tableId;
    }

    /**
     * 获取该页面在所属表中的页号。
     */
    public int getPageNumber() {
        return pgNo;
    }

    /**
     * 获取该页面的类型。
     */
    public int pgcateg() {
        return pgcateg;
    }

    /**
     * 返回该页面ID的哈希码。
     * 用于作为 HashMap 或 HashSet 的键时使用（例如 BufferPool 中）。
     */
    @Override
    public int hashCode() {
        return Objects.hash(tableId, pgNo, pgcateg);
    }

    /**
     * 判断两个 BTreePageId 是否相等。
     *
     * @param o 要比较的对象
     * @return 如果两个对象的 tableId、pgNo 和 pgcateg 都相同，则返回 true
     */
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof BTreePageId))
            return false;
        BTreePageId p = (BTreePageId) o;
        return tableId == p.tableId && pgNo == p.pgNo && pgcateg == p.pgcateg;
    }

    /**
     * 返回当前对象的字符串表示，便于调试输出。
     */
    public String toString() {
        return "(tableId: " + tableId + ", pgNo: " + pgNo + ", pgcateg: " + categToString(pgcateg) + ")";
    }

    /**
     * 序列化当前对象为整型数组，用于写入磁盘。
     * 数组长度应与构造函数参数数量一致。
     *
     * @return 整型数组表示的序列化数据
     */
    public int[] serialize() {
        int[] data = new int[3];

        data[0] = tableId;
        data[1] = pgNo;
        data[2] = pgcateg;

        return data;
    }
}
